# uncompyle6 version 3.2.3
# Python bytecode 3.6 (3379)
# Decompiled from: Python 3.6.8 |Anaconda custom (64-bit)| (default, Feb 21 2019, 18:30:04) [MSC v.1916 64 bit (AMD64)]
# Embedded file name: reporter\reports\compliance.py
from reporter.reports.basic_template import ReportTemplate
from io import StringIO
import jinja2, xmltodict, re
from reporter.reports.basic_template import NamedTempFileWithNormalizedWrite


class ComplianceReport(ReportTemplate):
    def __init__(self, sources, xml_name):
        super().__init__(sources)
        self.xml_path = "data/templates/reports/compliance/xml/" + xml_name
        with open(self.xml_path, "rb") as (f):
            self.compliance_dict = xmltodict.parse(f)
            self.compliance_dict = self.compliance_dict["Compliance"]
        self.description = self.compliance_dict["Info"]["Description"]
        self.disclaimer = self.compliance_dict["Info"]["Disclaimer"]
        self.title = self.compliance_dict["Info"]["Title"]
        self.compliance_dict = self.compliance_dict["Categories"]["Category"]
        for category in self.compliance_dict:
            associations = set()
            if category["Associations"] is not None:
                assoc_dict = category["Associations"]["Association"]
                if isinstance(assoc_dict, list):
                    for assoc in assoc_dict:
                        if "@AlertTag" in assoc:
                            associations.add(assoc["@AlertTag"])
                        else:
                            associations.add(assoc["@AlertGroup"])

                else:
                    associations.add(assoc_dict["@AlertTag"])
                category["Associations"] = associations

    def parts(self):
        template_loader = jinja2.FileSystemLoader(searchpath="data/templates/reports/")
        template_env = jinja2.Environment(loader=template_loader)
        template_vars = {}
        template = template_env.get_template("compliance/compliance_template.html")
        common_parts_template_vars = {}
        common_parts_template = template_env.get_template("common_parts_template.html")
        data = StringIO()
        data.write(common_parts_template.render({"template_part": "header"}))
        template_vars["compliance_name"] = self.title
        template_vars["compliance_description"] = self.encode_bb_codes(self.description)
        template_vars["compliance_disclaimer"] = self.encode_bb_codes(self.disclaimer)
        template_vars["date_generated"] = self.get_formatted_nowdate()
        template_vars["template_part"] = "body_start"
        data.write(template.render(template_vars))
        data.seek(0)
        yield data
        data = StringIO()
        with NamedTempFileWithNormalizedWrite() as (file_affected_items):
            with NamedTempFileWithNormalizedWrite() as (file_scanned_items):
                with NamedTempFileWithNormalizedWrite() as (file_glance):
                    with NamedTempFileWithNormalizedWrite() as (file_categories):
                        with NamedTempFileWithNormalizedWrite() as (
                            file_alerts_in_category
                        ):
                            for source in self.sources:
                                file_glance.seek(0)
                                file_glance.truncate()
                                file_categories.seek(0)
                                file_categories.truncate()
                                file_affected_items.seek(0)
                                file_affected_items.truncate()
                                file_scanned_items.seek(0)
                                file_scanned_items.truncate()
                                file_alerts_in_category.seek(0)
                                file_alerts_in_category.truncate()
                                vuln_type_categories = dict()
                                for location in source.locations():
                                    is_vulnerable = False
                                    for vulnerability, _, _ in source.vulnerabilities(
                                        location=location
                                    ):
                                        is_vulnerable = True
                                        break

                                    location["is_vulnerable"] = is_vulnerable
                                    common_parts_template_vars[
                                        "template_part"
                                    ] = "scanned_item"
                                    location["url"] = self.unquote_url(
                                        location.get("url") or ""
                                    )
                                    common_parts_template_vars["location"] = location
                                    file_scanned_items.write(
                                        common_parts_template.render(
                                            common_parts_template_vars
                                        )
                                    )

                                for category in self.compliance_dict:
                                    alert_cnt = 0
                                    file_alerts_in_category.seek(0)
                                    file_alerts_in_category.truncate()
                                    for (
                                        vulnerability,
                                        location,
                                        vulnerability_type,
                                    ) in source.vulnerabilities(
                                        tags=category["Associations"]
                                    ):
                                        alert_cnt += 1
                                        if (
                                            vulnerability_type["vt_id"]
                                            in vuln_type_categories
                                        ):
                                            vuln_type_categories[
                                                vulnerability_type["vt_id"]
                                            ].add(category["@Index"])
                                        else:
                                            vuln_type_categories[
                                                vulnerability_type["vt_id"]
                                            ] = set()
                                            vuln_type_categories[
                                                vulnerability_type["vt_id"]
                                            ].add(category["@Index"])
                                        vulnerability["location"] = location
                                        template_vars[
                                            "vulnerability_type"
                                        ] = vulnerability_type
                                        template_vars[
                                            "classifications"
                                        ] = self.get_classifications(vulnerability_type)
                                        template_vars["vulnerability"] = vulnerability
                                        template_vars[
                                            "template_part"
                                        ] = "alert_in_category"
                                        file_alerts_in_category.write(
                                            template.render(template_vars)
                                        )

                                    category_link = self.generate_link(
                                        category["@Index"]
                                    )
                                    template_vars["category_name"] = category["Title"]
                                    template_vars["category_index"] = category["@Index"]
                                    template_vars["alert_cnt"] = alert_cnt
                                    template_vars["category_link"] = category_link
                                    template_vars["template_part"] = "glance_item"
                                    file_glance.write(template.render(template_vars))
                                    template_vars["category_index"] = category["@Index"]
                                    template_vars["category_name"] = category["Title"]
                                    template_vars[
                                        "category_description"
                                    ] = self.encode_bb_codes(category["Description"])
                                    template_vars["alert_cnt"] = alert_cnt
                                    template_vars["category_link"] = category_link
                                    template_vars["template_part"] = "category_item"
                                    file_categories.write(
                                        template.render(template_vars)
                                    )
                                    file_alerts_in_category.seek(0)
                                    file_categories.write(
                                        file_alerts_in_category.read()
                                    )

                                previous_loc_id = -1
                                for (
                                    vulnerability,
                                    location,
                                    vulnerability_type,
                                ) in source.vulnerabilities():
                                    if (
                                        vulnerability_type["vt_id"]
                                        in vuln_type_categories
                                    ):
                                        vulnerability["location"] = location
                                        template_vars["categories"] = self.sorted_set(
                                            vuln_type_categories[
                                                vulnerability_type["vt_id"]
                                            ]
                                        )
                                        template_vars["vulnerability"] = vulnerability
                                        template_vars[
                                            "vulnerability_type"
                                        ] = vulnerability_type
                                        template_vars[
                                            "classifications"
                                        ] = self.get_classifications(vulnerability_type)
                                        template_vars["show_header"] = (
                                            location["loc_id"] != previous_loc_id
                                        )
                                        template_vars["template_part"] = "affected_item"
                                        file_affected_items.write(
                                            template.render(template_vars)
                                        )
                                        previous_loc_id = location["loc_id"]

                                template_vars[
                                    "scan_info"
                                ] = self.get_well_formed_scan_info(source)
                                file_glance.seek(0)
                                template_vars["glance_summary"] = file_glance.read()
                                file_categories.seek(0)
                                template_vars["categories"] = file_categories.read()
                                file_affected_items.seek(0)
                                template_vars[
                                    "affected_items"
                                ] = file_affected_items.read()
                                file_scanned_items.seek(0)
                                template_vars[
                                    "scanned_items"
                                ] = file_scanned_items.read()
                                template_vars["template_part"] = "structure"
                                data.write(template.render(template_vars))
                                data.seek(0)
                                yield data
                                data = StringIO()

        template_vars["template_part"] = "body_end"
        data.write(template.render(template_vars))
        data.seek(0)
        yield data

    @staticmethod
    def sorted_set(data):
        return sorted(
            data,
            key=lambda key: [
                int(c) if c.isdigit() else c for c in re.split("([0-9]+)", key)
            ],
        )

    @staticmethod
    def encode_bb_codes(text_with_bb_code):
        result = text_with_bb_code.replace("[p]", "<p>")
        result = result.replace("[/p]", "</p>")
        result = result.replace("[b]", "<b>")
        result = result.replace("[/b]", "</b>")
        result = result.replace("[code]", "<code>")
        result = result.replace("[/code]", "</code>")
        result = result.replace("[ul]", "<ul>")
        result = result.replace("[/ul]", "</ul>")
        result = result.replace("[li]", "<li>")
        result = result.replace("[/li]", "</li>")
        return result
